03. More Complex Paths

More Complex Paths

In the previous concept you moved the car forward in a straight line. How about creating more interesting paths?

Driving the car in a circular path

Driving the car in a circular path

```cpp
vector next_x_vals;
vector next_y_vals;

double pos_x;
double pos_y;
double angle;
int path_size = previous_path_x.size();

for (int i = 0; i < path_size; ++i) {
next_x_vals.push_back(previous_path_x[i]);
next_y_vals.push_back(previous_path_y[i]);
}

if (path_size == 0) {
pos_x = car_x;
pos_y = car_y;
angle = deg2rad(car_yaw);
} else {
pos_x = previous_path_x[path_size-1];
pos_y = previous_path_y[path_size-1];

double pos_x2 = previous_path_x[path_size-2];
double pos_y2 = previous_path_y[path_size-2];
angle = atan2(pos_y-pos_y2,pos_x-pos_x2);
}

double dist_inc = 0.5;
for (int i = 0; i < 50-path_size; ++i) {
next_x_vals.push_back(pos_x+(dist_inc) cos(angle+(i+1) (pi()/100)));
next_y_vals.push_back(pos_y+(dist_inc) sin(angle+(i+1) (pi()/100)));
pos_x += (dist_inc) cos(angle+(i+1) (pi()/100));
pos_y += (dist_inc) sin(angle+(i+1) (pi()/100));
}

msgJson["next_x"] = next_x_vals;
msgJson["next_y"] = next_y_vals;
```

Using Previous Path Points

The code snippet above builds a 50 point path, as in the previous experiment. But this code snippet starts the new path with whatever previous path points were left over from the last cycle. Then we append new waypoints, until the new path has 50 total waypoints.

Using information from the previous path ensures that there is a smooth transition from cycle to cycle. But the more waypoints we use from the previous path, the less the new path will reflect dynamic changes in the environment.

Ideally, we might only use a few waypoints from the previous path and then generate the rest of the new path based on new data from the car's sensor fusion information.

Timing

The simulator runs a cycle every 20 ms (50 frames per second), but your C++ path planning program will provide a new path at least one 20 ms cycle behind. The simulator will simply keep progressing down its last given path while it waits for a new generated path.

This means that using previous path data becomes even more important when higher latency is involved. Imagine, for instance, that there is a 500ms delay in sending a new path to the simulator. As long as the new path incorporates a sufficient length of the previous path, the transition will still be smooth.

A concern, though, is how accurately we can predict other traffic 1-2 seconds into the future. An advantage of newly generated paths is that they take into account the most up-to-date state of other traffic.

Setting Point Paths with Latency

As a mentioned, your C++ path planner will at the very least be one cycle behind the simulator because the C++ program can't receive and send data on the same cycle. As a result, any path that the simulator receives will be from the perspective of a previous cycle. This might mean that by the time a new path reaches the simulator, the vehicle has already passed the first few waypoints on that path.

Luckily you don't have to worry about this too much. The simulator has built-in tools to deal with this timing difference. The simulator actually expects the received path to be a little out of date compared to where the car is, and the simulator will consider which point on the received path is closest to the car and adjust appropriately.